"""
Copyright (c) 2022 Guangdong University of Technology
PhotLab is licensed under [Open Source License].
You can use this software according to the terms and conditions of the [Open Source License].
You may obtain a copy of [Open Source License] at: [https://open.source.license/]

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.

See the [Open Source License] for more details.

Author: Meng Xiang, Junjiang Xiang
Created: 2023/8/19
Supported by: National Key Research and Development Program of China

"""
import numpy as np
from scipy import signal
from phot import logger


def circshift(u, shift_index):
    h = len(u)
    if shift_index < 0:
        u = np.vstack((u[-shift_index:, :], u[:-shift_index, :]))
    else:
        u = np.vstack((u[(h-shift_index):, :], u[:(h-shift_index), :]))
    return u


def fine_synchronization(Tr_input_x, Re_input_X):

    data2 = np.real(Re_input_X) - 1j * np.imag(Re_input_X)
    data2 = data2[::-1]
    data = signal.lfilter(data2, 1, Tr_input_x)
    matric_error = np.abs(data)
    N = np.abs(np.sum(Re_input_X * (np.real(Re_input_X) - 1j * np.imag(Re_input_X))))
    matric_error = matric_error / N
    Start_Index = np.argmax(matric_error)
    Start_Index = Start_Index - len(Re_input_X)

    return Start_Index


def synchronization(input, traning_input, up_sampling_factor):
    """同步
        Args:
            input[0]: 输入X偏振信号, numpy类型
            input[1]: 输入Y偏振信号, numpy类型
            traning_input[0]: 输入X偏振训练样本，尺寸为(n, 1)
            traning_input[1]: 输入Y偏振训练样本，尺寸为(n, 1)

        Returns:
            output[0]：输出X偏振信号
            output[1]:输出Y偏振信号
            traning_output[0]：输出X偏振训练样本
            traning_output[1]：输出Y偏振训练样本
        """
    Re_X = input[0]
    Re_Y = input[1]
    Traning_Sample_X = np.array(traning_input[0])
    Traning_Sample_Y = np.array(traning_input[1])
    if len(Traning_Sample_X.shape) == 1:
        Traning_Sample_X = np.expand_dims(Traning_Sample_X, axis=1)
        Traning_Sample_Y = np.expand_dims(Traning_Sample_Y, axis=1)

    Start_Index_X_1 = fine_synchronization(Re_X[0: 50000 * up_sampling_factor: up_sampling_factor, 0], Traning_Sample_X[0:2000, 0])
    Start_Index_Y_1 = fine_synchronization(Re_Y[0: 50000 * up_sampling_factor: up_sampling_factor, 0], Traning_Sample_Y[0:2000, 0])
    # print("Start_Index X_1:  {}, Start_Index Y_1:  {},".format(Start_Index_X_1 + 1, Start_Index_Y_1 + 1))
    logger.info("两个偏振第一次对准的帧头")
    logger.info("Start_Index_X_1: {} Start_Index_Y_1: {}".format(Start_Index_X_1 + 1, Start_Index_Y_1 + 1))

    Re_X = Re_X[(Start_Index_X_1 + 1) * up_sampling_factor:-1000, 0]
    Re_Y = Re_Y[(Start_Index_Y_1 + 1) * up_sampling_factor:-1000, 0]
    Traning_Sample_X = Traning_Sample_X[:int(np.floor(len(Re_X) / up_sampling_factor)), 0]
    Traning_Sample_Y = Traning_Sample_Y[:int(np.floor(len(Re_Y) / up_sampling_factor)), 0]

    output = [Re_X, Re_Y]
    traning_output = [Traning_Sample_X, Traning_Sample_Y]

    return output, traning_output



